package com.quartz.util;


import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MapUtil {

    public static <T> List<T> castMapToBean(List<Map<String, Object>> list, Class<T> clazz) throws Exception {
        if (list == null || list.size()==0) {
            return null;
        }
        List<T> tList = new ArrayList<T>();
        // 获取类中声明的所有字段
        Field[] fields = clazz.getDeclaredFields();

        T t;
        for (Map<String, Object> map : list) {
            // 每次都先初始化一遍,然后再设置值
            t = clazz.newInstance();
            for (Field field : fields) {
                // 把序列化的字段去除掉
                if (!"serialVersionUID".equals(field.getName())) {
                    // 由于Field都是私有属性，所有需要允许修改
                    field.setAccessible(true);

                    // 设置值, 类型要和vo中的属性名称对应好,不然会报类型转换错误
                    field.set(t, map.get(field.getName()));
                }
            }
            tList.add(t); // 把转换好的数据添加到集合中
        }
        return tList;
    }

    public static <T>  T mapToBean (Map<String, Object> map, Class<T> clazz)  {
        T instance = null;
        try {
            instance = clazz.newInstance();
            Field[] declaredFields = instance.getClass().getDeclaredFields();
            for (Field field : declaredFields) {
                field.setAccessible(true);
                String name = field.getName();
                Object value = map.get(name);
                field.set(instance,value);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return  instance;
    }
    public static<T>  T mapToForceBean (Map<String, Object> map, Class<T> clazz)  {
        T instance = null;
        try {
            instance = clazz.newInstance();
            Field[] declaredFields = instance.getClass().getDeclaredFields();
            for (Field field : declaredFields) {
                field.setAccessible(true);
                String name = field.getName();
                Object value = map.get(name);
                ConversionService sharedInstance = DefaultConversionService.getSharedInstance();

                if(value!=null&&sharedInstance.canConvert(value.getClass(),field.getType())){
                     value = sharedInstance.convert(value, field.getType());
                }
                field.set(instance,value);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return  instance;
    }

    public static<T> List<T> mapToBean (List<Map<String, Object>> mapList, Class<T> clazz)  {
        List<T> list = new ArrayList<>(mapList.size());
        for (Map<String, Object> map : mapList) {
            T instance = null;
            try {
                instance = clazz.newInstance();
                Field[] declaredFields = instance.getClass().getDeclaredFields();
                for (Field field : declaredFields) {
                    field.setAccessible(true);
                    String name = field.getName();
                    Object value = map.get(name);
                    if (value==null){
                        continue;
                    }
                    field.set(instance,value);
                }
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            list.add(instance);
        }
        return list;
    }

    public static Map<String,Object> convertBeanToMap(Object bean) throws IntrospectionException,IllegalAccessException, InvocationTargetException {
        Class type = bean.getClass();
        Map<String,Object> returnMap = new HashMap<String, Object>();
        BeanInfo beanInfo = Introspector.getBeanInfo(type);
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (int i = 0; i < propertyDescriptors.length; i++) {
            PropertyDescriptor descriptor = propertyDescriptors[i];
            String propertyName = descriptor.getName();
            if (!propertyName.equals("class")) {
                Method readMethod = descriptor.getReadMethod();
                Object result = readMethod.invoke(bean, new Object[0]);
                if (result != null) {
                    returnMap.put(propertyName, result);
                } else {
                    returnMap.put(propertyName, "");
                }
            }
        }
        return returnMap;
    }

}
